#ifndef MULTITREE_H_
#define MULTITREE_H_
#include <stdio.h>
/*Multitree - the way to represent an expression.*/
#include "Symbol.h"

struct ListOfChilds_;

typedef struct{
	Symbol symbol;
	struct ListOfChilds_ * childs;
}Multitree;

typedef struct ListOfChilds_{
	Multitree * subtree;
	struct ListOfChilds_ * next;
	int inverted;
} ListOfChilds;

/*These functions should not be used directly by user*/
//	std::ostream & output_tree(Multitree * tree, std::ostream & stream);
void rehang_tree(Multitree * tree); /*There should not be PLUS operator as child of another PLUS in tree. And same holds for MULTIPLY operator. This function merges such nodes, if needed. */
void sort_tree(Multitree * tree); /* Sorts the sons of some operations. */
Multitree * reduce_tree(Multitree * tree); /*internal to canonicalize*/
Multitree * diff_tree(Multitree * tree, char * variable);
/*Multitree * diff_tree(Multitree * tree, const Multitree * variable); */
Multitree * replace_variable_tree(Multitree * original, const char * variable, Multitree * with);
/*Multitree * replace_variable_tree(Multitree * original, const Multitree * variable, Multitree * with);*/
Multitree * expand_tree(Multitree * tree);
Multitree * canonicalize_tree(Multitree * tree); /*Should be called at the end of all user functions*/
Number * numeric(Multitree * tree);
Multitree * taylorize(Multitree * tree, Multitree * center, unsigned short int terms, char * variable); /* Shouldn't there be Multitree * center? I think so.*/
/*Multitree * taylorize(Multitree * tree, const Multitree * center, unsigned short int terms, char * variable); */
/*C constructors :-) */
Multitree * give_me_empty_tree();
Multitree * give_me_tree_with_two_childs();
Multitree * give_me_tree_with_two_incomplete_childs(); /*long name, but user will not use it hopefully*/
ListOfChilds * give_me_empty_child();
Multitree * treefromnum(Number * number);

/*Probably not needed - they delete the tree - but will leave them there*/
void delete_tree(Multitree * tree);
void delete_childs(ListOfChilds * childs);

/*functions for user*/
int treecmp(const Multitree * first, const Multitree * second); /*Compares trees - similar to strcmp.*/
char * treetostring(Multitree * tree); 
Multitree* copy_tree(Multitree * tree);

Multitree * inttotree(long long int i);
Multitree * doubletotree(long double d);
Multitree * treevariable(char * var);
Multitree * treeconstant(char * name, Multitree * number);
Multitree * treeplus(Multitree * first, Multitree * second);
Multitree * treeminus(Multitree * first, Multitree * second);
Multitree * treemul(Multitree * first, Multitree * second);
Multitree * treediv(Multitree * first, Multitree * second);
Multitree * treepow(Multitree * first, Multitree * second);
Multitree * treesin(Multitree * arg);
Multitree * treecos(Multitree * arg);
Multitree * treetan(Multitree * arg);
Multitree * treeln(Multitree * arg);
Multitree * treediff(Multitree * expression, Multitree * variable);
Multitree * tree_replace_var(Multitree * expression, Multitree * variable, Multitree * by_what);
Multitree * treeexpand(Multitree * tree); /*fo consistency - users function names begin with 'tree'. And to check parameter*/
Multitree * treetaylor(Multitree * tree, Multitree * center, unsigned short int terms, Multitree * variable);

#endif /*MULTITREE_H_*/
